package com.zdyl.fileReplaceTool.utils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class CommonUtils {

    public static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(CommonUtils.class);

    /**
     * 获取文件夹下所有文件的名称 + 模糊查询（当不需要模糊查询时，queryStr传空或null即可）
     * 1.当路径不存在时，map返回retType值为1
     * 2.当路径为文件路径时，map返回retType值为2，文件名fileName值为文件名
     * 3.当路径下有文件夹时，map返回retType值为3，文件名列表fileNameList，文件夹名列表folderNameList
     *
     * @param folderPath 路径
     * @param queryStr   模糊查询字符串
     * @return
     */
    public HashMap<String, Object> getFilesName(String folderPath, String queryStr, Boolean isNameCase) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        List<String> fileNameList = new ArrayList<String>();//文件名列表
        File f = new File(folderPath);
        if (!f.exists()) { //路径不存在
            map.put("retType", "1");
        } else {
            boolean flag = f.isDirectory();
            if (!flag) { //路径为文件
                map.put("retType", "2");
                map.put("fileName", f.getName());
            } else { //路径为文件夹
                map.put("retType", "3");
                fileNameList(f, queryStr, isNameCase, fileNameList);
                map.put("fileNameList", fileNameList);
            }
        }
        return map;
    }

    /**
     * 递归获取匹配的文件列表
     *
     * @param f
     * @param queryStr
     * @param fileNameList
     */
    public void fileNameList(File f, String queryStr, Boolean isNameCase, List<String> fileNameList) {
        File[] fa = f.listFiles();
        queryStr = queryStr == null ? "" : queryStr;//若queryStr传入为null,则替换为空（indexOf匹配值不能为null）
        assert fa != null;
        for (File fs : fa) {
            if (fs.isDirectory()) {
                fileNameList(fs, queryStr, isNameCase, fileNameList);
            } else {
                if (isNameCase){
                    if (fs.getName().contains(queryStr)) {
                        fileNameList.add(fs.getAbsolutePath());
                    }
                }else {
                    if (fs.getName().toLowerCase().contains(queryStr.toLowerCase())) {
                        fileNameList.add(fs.getAbsolutePath());
                    }
                }
            }
        }

    }

    /**
     *文件修改
     * @param file 文件名称
     * @param oldStr   要修改的字符串
     * @param newStr   新的字符串
     * @return
     */
    //  文件修改
    public int modifyFileContent(File file, String oldStr, String newStr, Boolean isStrCase) {
        ///定义一个随机访问文件类的对象
        RandomAccessFile raf = null;
        //获取文件目录用于创建临时文件
        File directory = new File(String.valueOf(file.getParentFile()));
        int count = 0;
        try {
            //获取文件编码格式
            String code = FileCharsetCheckUtils.getFileCharset(file);
            //初始化对象,以"rw"(读写方式)访问文件
            raf = new RandomAccessFile(file, "rw");
            logger.info("初始化文件成功：" + file.getAbsolutePath());
            //读取文件长度
            long length = raf.length();
            //判断长度
            if (length == 0L) {
                return 0;
            } else {
                //初始化临时文件
                File outFile = File.createTempFile(file.getName(), ".tmp", directory);
                logger.info("初始化临时文件成功：" + outFile.getAbsolutePath());
                //临时文件输出
                FileOutputStream fos = new FileOutputStream(outFile);
                PrintWriter out = new PrintWriter(fos);
                long next = 0;
                while (next < length-1) {
                    //开始读取
                    raf.seek(next);
                    //如果读取到\n代表是读取到一行
                    if (next==0){
                        //使用readLine获取当前行
                        String line = new String(raf.readLine().getBytes(StandardCharsets.ISO_8859_1), code);
                        if (!isStrCase){
                            // 查找要替换的内容
                            if (line.toLowerCase().contains(oldStr.toLowerCase())) {
                                //更新计数器
                                count+=getNum(line.toLowerCase(),oldStr.toLowerCase());
                                //修改内容,line读出整行数据
                                line = line.replaceAll("(?i)" + oldStr, newStr);
                            }
                        }else {
                            // 查找要替换的内容
                            if (line.contains(oldStr)) {
                                //更新计数器
                                count+=getNum(line,oldStr);
                                //修改内容,line读出整行数据
                                line = line.replaceAll(oldStr, newStr);
                            }
                        }
                        out.println(line);
                    }else if (raf.readByte() == '\n'){
                        //使用readLine获取当前行
                        String line = new String(raf.readLine().getBytes(StandardCharsets.ISO_8859_1), code);
                        if (!isStrCase){
                            // 查找要替换的内容
                            if (line.toLowerCase().contains(oldStr.toLowerCase())) {
                                //更新计数器
                                count+=getNum(line.toLowerCase(),oldStr.toLowerCase());
                                //修改内容,line读出整行数据
                                line = line.replaceAll("(?i)" + oldStr, newStr);
                            }
                        }else {
                            // 查找要替换的内容
                            if (line.contains(oldStr)) {
                                //更新计数器
                                count+=getNum(line,oldStr);
                                //修改内容,line读出整行数据
                                line = line.replaceAll(oldStr, newStr);
                            }
                        }
                        out.println(line);
                    }
                    next++;
                }
                out.flush();
                out.close();
                raf.close();
                // 删除原始文件
                if (file.delete()){
                    logger.info(file.getAbsolutePath() + "删除文件成功！");
                }else {
                    logger.info(file.getAbsolutePath() + "删除文件失败！");
                }
                // 把临时文件改名为原文件名
                if (outFile.renameTo(file)){
                    logger.info(outFile.getAbsolutePath() + "临时文件改名成功！");
                }else {
                    logger.info(outFile.getAbsolutePath() + "临时文件改名失败！");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                assert raf != null;
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return count;
    }

    public int getNum(String oriStr,String aimStr){
        String[] split = oriStr.split(aimStr);
        return split.length - 1;
    }

    /**
     * 读出配置文件
     *
     * @param file 文件
     * @return
     */
    public String getConfig(File file) {

        //判断该文件是否存在，可读
        if (!file.exists() || file.isDirectory() || !file.canRead()) {
            return null;
        }
        StringBuilder result = new StringBuilder();
        //很多中读取模式，选择只读模式
        RandomAccessFile read = null;
        try {
            read = new RandomAccessFile(file, "rw");
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = read.read(buf)) != -1) {
                result.append(new String(buf));
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭文件
            if (read != null) {
                try {
                    read.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result.toString();
    }
}
